<?php
/**
 * crcl/base
 *
 * Copyright 2013 CRCL - André Sabosch - info@crcl.de
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * System related functions
 */

namespace crcl\base;

interface ITemplate
{
  /**
   * factory: returns template object with loaded template from file
   *
   * @static
   * @param   $sFile      string  File with template
   * @return  $oTemplate  ITemplate
   */
  public static function fromFile($sFile);

  /**
   * Sets value to template
   *
   * @param $key    mixed Name of value
   * @param $value  mixed Value
   */
  public function setValue($key, $value);

  /**
   * Sets values to template
   *
   * @param $aValues
   */
  public function setValues($aValues);

  /**
   * Returns values object
   * @return \crcl\base\template\IValues
   */
  public function getValues();

  /**
   * Returns (freshly) compiled template
   *
   * @return string
   */
  public function compile();

  /**
   * Executes template. Expects compiled template if not local
   */
  public function execute();

  public function executeAsString();
}

class Template implements ITemplate
{
  public static function fromFile($sFile)
  {
    $oTemplate = new Template($sFile);
    return $oTemplate;
  }

  public function setValue($key, $value)
  {
    $this->oValues->set($key, $value);
  }

  public function setValues($aValues)
  {
    foreach ($aValues as $key => $value)
    {
      $this->setValue($key, $value);
    }
  }

  public function getValues()
  {
    return $this->oValues;
  }

  public function compile()
  {
    $sContent = $this->getContent();
    $oCompiler = template\Compiler::fromString($sContent);
    $sContent = $oCompiler->compile();
    return $sContent;
  }

  public function execute()
  {
    $oCache = template\Cache::fromTemplate($this->sFile);
    if (Tier::isLocal())
    {
      $sContent = $this->compile();
      $oCache->set($sContent);
    }
    include $oCache->getFile();
    $fExecuter($this->oValues);
    unset($fExecuter);
  }

  public function executeAsString()
  {
    $oException = \NULL;
    \ob_start();
    try
    {
      $this->execute();
    }
    catch (\Exception $e)
    {
      $oException = $e;
    }
    $sOutput = \ob_get_clean();
    if (!\is_null($oException))
    {
      throw $e;
    }
    return $sOutput;
  }

  /** PRIVATE *************************************************************************************/

  private $sFile = \NULL;
  private $oValues = \NULL;

  private function __construct($sFile)
  {
    $this->sFile = $sFile;

    $this->oValues = new template\Values();
  }

  private function getContent()
  {
    $sFile = \crcl\base\application\Path::getDirectory(\crcl\base\application\Path::DIR_TEMPLATES) .
      $this->sFile;
    $content = @\file_get_contents($sFile);
    if ($content === \FALSE)
    {
      throw new template\Exception(
        'Missing file',
        template\Exception::ERROR_MISSINGFILE,
        array('file' => $sFile, 'template' => $this->sFile));
    }
    return $content;
  }
}